<?php
// $Id: task.php 24 2010-11-11 07:33:55Z mjohnson60@gmail.com $


$main = 'task';

/**
 * task()
 * 
 * this function is called immediately after all variables have been loaded and all forms
 * have been validated and submitted
 * 
 * @param mixed $vars
 * @return void
 */
function task(&$vars)
{
	system_add_styles('assets/css/style.css');
	system_add_js('assets/js/jquery.js');
	
	system_page_title('Tasks');
	$breadcrumbs = array(
		'Home' => array(
			'#title' => 'Home', 
			'#anchor' => 'Home', 
			'#attributes' => array(
				'class' => 'breadcrumb'
			), 
			'#href' => base_path()
		)
	);
	
	if (isset($GLOBALS['op']) && $GLOBALS['op'] == 'edit')
	{
		$breadcrumbs['Edit'] = array(
			'#title' => 'Edit Task', 
			'#anchor' => 'Edit Task', 
			'#attributes' => array(
				'class' => 'breadcrumb'
			)
		);
	}
	else
	{
		system_add_js('assets/js/selectable.table.js');
	}
	
	system_breadcrumbs($breadcrumbs);
}

/**
 * task_prerender_page()
 * 
 * this function sets the content variable for the page.tpl.php template and any other data
 * such as page titles, etc.
 * 
 * This function also chooses which forms to display based on query string parameters
 * (ie. ?op=edit or ?op=add, etc.)
 * 
 * @param mixed $vars
 * @return void
 */
function task_prerender_page(&$vars)
{
	global $task_form, $task_table, $op, $subop;
	
	$output = '';
	switch ($op)
	{
		case 'add':
		case 'edit':
		case 'clone':
		case 'delete':
			if (isset($vars['query']['tid']))
			{
				if (!isset($task_form))
				{
					if ($op != 'delete')
					{
						task_edit_form($vars['query']['tid']);
					}
					else
					{
						task_delete_confirmation_form($vars['query']['tid']);
					}
				}
				
				$output = form_build($task_form, 'task_view_' . $op);
				system_page_title(ucwords($GLOBALS['op']) . ' Tasks');
			}
			else
			{
				system_redirect(base_path() . 'task');
			}
			
			break;
		default:
			if (!isset($task_form))
			{
				$task_form = task_default_form();
			}
			
			if (!isset($task_table))
			{
				$task_table = task_default_table();
			}
			
			$add_button = array(
				'#type' => 'button', 
				'#value' => 'add', 
				'#id' => unique_id('add-task'), 
				'#attributes' => array(
					'class' => 'ui-button add form-submit', 
					'onclick' => "window.location = '" . base_path() . "task?op=add&tid=0';"
				), 
				'#title' => '+ Add Task', 
				'#prefix' => '<div class="form-item right form-submit">', 
				'#suffix' => '</div>'
			);
			
			if (isset($subop) && $subop == 'search')
			{
				system_page_title('Search Tasks');
				
				$reset_button = array(
					'#type' => 'button', 
					'#value' => 'clear', 
					'#id' => unique_id('clear-search'), 
					'#attributes' => array(
						'class' => 'ui-button clear form-submit', 
						'onclick' => "window.location = '" . base_path() . "task';"
					), 
					'#title' => 'Clear Search', 
					'#prefix' => '<div class="form-item form-submit">', 
					'#suffix' => '</div>'
				);
			}
			else
			{
				system_page_title('Tasks');
			}
			
			$form_output = form_build($task_form, 'task_view' . (empty($op) ? '' : '_' . $op)) . render('generic_button', $add_button) . (isset($reset_button) ? render('generic_button', $reset_button) : '');
			
			$table_output = render('table', $task_table);
			
			$output .= $form_output . $table_output;
			
			break;
	}
	
	$vars['content'] = $output;
}

/**
 * task_default_form()
 * 
 * This function returns the default form for the page (ie. the form that is rendered) with no 
 * query string parameters
 * 
 * in this case, this form is a search form for the tasks table
 * 
 * @return
 */
function task_default_form()
{
	$form_id = unique_id('task-default-view');
	
	$text_field_size = 30;
	$form = array(
		
		'#id' => $form_id, 
		'#action' => base_path() . '?task?op=view&subop=search', 
		'#method' => 'POST', 
		'#callback' => 'task_search_submit', 
		'#attributes' => array(
			'class' => 'container-inline'
		), 
		'#inputs' => array(
			'description' => array(
				'#type' => 'textfield', 
				'#id' => unique_id('filter-description'), 
				'#title' => 'Description', 
				'#size' => $text_field_size
			), 
			'developer' => array(
				'#type' => 'textfield', 
				'#id' => unique_id('filter-developer'), 
				'#title' => 'Developer', 
				'#size' => $text_field_size
			), 
			'feature' => array(
				'#type' => 'textfield', 
				'#id' => unique_id('filter-feature'), 
				'#title' => 'Feature', 
				'#size' => $text_field_size
			), 
			'milestone' => array(
				'#type' => 'textfield', 
				'#id' => unique_id('filter-milestone'), 
				'#title' => 'Milestone', 
				'#size' => $text_field_size
			), 
			'status' => array(
				'#type' => 'select', 
				'#title' => 'Status', 
				'#options' => array(
					'NULL' => array(
						'#title' => '----------------', 
						'#value' => 'NULL'
					), 
					'P' => array(
						'#title' => 'Pending', 
						'#value' => 'P'
					), 
					'I' => array(
						'#title' => 'In Progress', 
						'#value' => 'I'
					), 
					'C' => array(
						'#title' => 'Completed', 
						'#value' => 'C'
					)
				)
			), 
			'search_wrapper' => array(
				'#type' => 'html', 
				'#value' => '<div class="form-item-wrapper search">'
			), 
			'search' => array(
				'#type' => 'submit', 
				'#value' => 'Search', 
				'#id' => unique_id('search'), 
				'#attributes' => array(
					'class' => 'ui-button search', 
					'onclick' => "$('#" . $form_id . "').get(0).setAttribute('action', '" . base_path() . "task?op=view&subop=search');"
				)
			), 
			'search_wrapper_close' => array(
				'#type' => 'html', 
				'#value' => '</div>'
			)
		)
	);
	
	return $form;
}

/**
 * task_default_table()
 * 
 * This function returns the default table for the page (ie. the table that is rendered) with no 
 * query string parameters
 * 
 * in this case, this returns a table that lists all tasks and related task data
 * 
 * @return
 */
function task_default_table()
{
	$result = db_query(Task::default_query() . ' ORDER BY t.description');
	
	$headers = array(
		'', 
		'Description', 
		'Developer', 
		'Feature', 
		'Milestone', 
		'EET', 
		'Status'
	);
	
	$rows = array();
	while ($task = db_fetch_array($result))
	{
		$links = a(array(
			'#href' => base_path() . 'task?op=edit&tid=' . $task['tid'], 
			'#anchor' => 'Edit', 
			'#attributes' => array(
				'class' => 'action-link edit'
			), 
			'#title' => 'Edit'
		)) . a(array(
			'#href' => base_path() . 'task?op=clone&tid=' . $task['tid'], 
			'#anchor' => 'Clone', 
			'#attributes' => array(
				'class' => 'action-link'
			), 
			'#title' => 'Clone'
		));
		$rows[] = array(
			
			'#cells' => array(
				'edit' => $links, 
				'description' => $task['description'], 
				'developer' => $task['developer'], 
				'feature' => $task['feature'], 
				'milestone' => $task['milestone'], 
				'eet' => (int) ($task['eet'] / 86400) . ' days', 
				'status' => Task::status_string($task['status'])
			)
		);
	}
	
	$table_id = unique_id('task-table');
	$task_table = array(
		'#attributes' => array(
			'id' => $table_id, 
			'border' => 1, 
			'cellspacing' => 0, 
			'cellpadding' => 8, 
			'class' => 'selectable data-list-table'
		), 
		'#header' => $headers, 
		'#rows' => $rows
	);
	
	return $task_table;
}

/**
 * task_search_submit()
 * 
 * @param mixed $form_result
 * @return void
 */
function task_search_submit(&$form_result)
{
	global $task_table, $task_form;
	
	$where = array();
	$params = array();
	
	$values = $form_result['values'];
	
	$task_form = task_default_form();
	
	if (isset($values['description']))
	{
		$where[] = "t.description LIKE '%%%s%%'";
		$params[] = $values['description'];
		$task_form['#inputs']['description']['#value'] = $values['description'];
	}
	
	if (isset($values['developer']))
	{
		$where[] = "d.name LIKE '%%%s%%'";
		$params[] = $values['developer'];
		$task_form['#inputs']['developer']['#value'] = $values['developer'];
	}
	
	if (isset($values['feature']))
	{
		$where[] = "f.description LIKE '%%%s%%'";
		$params[] = $values['feature'];
		$task_form['#inputs']['feature']['#value'] = $values['feature'];
	}
	
	if (isset($values['milestone']))
	{
		$where[] = "m.name LIKE '%%%s%%'";
		$params[] = $values['milestone'];
		$task_form['#inputs']['milestone']['#value'] = $values['milestone'];
	}
	
	if (isset($values['status']) && Task::status_string($values['status']) !== FALSE)
	{
		$where[] = "t.status='%s'";
		$params[] = $values['status'];
		$task_form['#inputs']['status']['#options'][$values['status']]['#selected'] = TRUE;
	}
	
	$sql = Task::default_query();
	$sql .= ' AND (' . implode(' AND ', $where) . ') ORDER BY t.description';
	$result = db_query($sql, $params);
	
	$headers = array(
		'', 
		'Description', 
		'Developer', 
		'Feature', 
		'Milestone', 
		'EET', 
		'Status'
	);
	$rows = array();
	while ($task = db_fetch_array($result))
	{
		$rows[] = array(
			
			'#cells' => array(
				
				'edit' => a(array(
					'#href' => base_path() . 'task?op=edit&tid=' . $task['tid'], 
					'#anchor' => 'Edit', 
					'#attributes' => array(
						'class' => 'action-link edit'
					)
				)) . a(array(
					'#href' => base_path() . 'task?op=clone&tid=' . $task['tid'], 
					'#anchor' => 'Clone', 
					'#attributes' => array(
						'class' => 'action-link clone'
					), 
					'#title' => 'Clone'
				)), 
				'description' => $task['description'], 
				'developer' => $task['developer'], 
				'feature' => $task['feature'], 
				'milestone' => $task['milestone'], 
				'eet' => (int) ($task['eet'] / 86400) . ' days', 
				'status' => Task::status_string($task['status'])
			)
		);
	}
	
	if (empty($rows))
	{
		$rows[] = array(
			'#cells' => array(
				'no_results' => array(
					'#value' => '<h2 style="text-align:center;">Your search returned no results.</h2>', 
					'#attributes' => array(
						'colspan' => count($headers)
					)
				)
			)
		);
	}
	
	$table_id = unique_id('task-table');
	$task_table = array(
		'#attributes' => array(
			'id' => $table_id, 
			'border' => 1, 
			'cellspacing' => 0, 
			'cellpadding' => 8, 
			'class' => 'selectable left data-list-table'
		), 
		'#header' => $headers, 
		'#rows' => $rows
	);
}

/**
 * _task_select_array()
 * 
 * @param mixed $inputs
 * @param mixed $table
 * @param mixed $name
 * @param mixed $id
 * @param mixed $task
 * @return void
 */
function _task_select_array(&$inputs, $table, $name, $id, $task)
{
	$options = array();
	if ($task->tid == 0)
	{
		$options[0] = array(
			'#title' => 'Please choose a ' . $table, 
			'#value' => 0, 
			'#selected' => TRUE
		);
	}
	
	$result = db_query('SELECT ' . $name . ', ' . $id . ' FROM ' . $table . ' WHERE ' . $id . ' > 0 ORDER BY ' . $name . ' ASC');
	
	while ($obj = db_fetch_array($result))
	{
		$options[$obj[$id]] = array(
			'#title' => $obj[$name], 
			'#value' => $obj[$id], 
			'#selected' => ($obj[$id] == $task->{$id} ? TRUE : FALSE)
		);
	}
	
	$inputs[$table] = array(
		'#type' => 'select', 
		'#title' => ucwords($table) . 's', 
		'#options' => $options
	);
}

/**
 * task_edit_form()
 * 
 * This is the form that is rendered when editing or adding a task
 * 
 * @param mixed $tid
 * @return void
 */
function task_edit_form($tid, $values = array())
{
	global $task_form, $op;
	
	$eet = '';
	if (!empty($values))
	{
		$task = new Task(array(
			'eet' => Task::eet_convert(array(
				'days' => abs($values['eet_days']), 
				'hours' => abs($values['eet_hours'])
			)), 
			'did' => $values['developer'], 
			'fid' => $values['feature'], 
			'mid' => $values['milestone'], 
			'description' => $values['description'], 
			'details' => $values['details'], 
			'status' => $values['status'], 
			'tid' => $tid
		));
		
		$eet = array(
			'days' => $values['eet_days'], 
			'hours' => $values['eet_hours']
		);
	}
	else if (!empty($tid))
	{
		$task = new Task($tid);
		$eet = $task->eet_value();
	}
	else
	{
		$task = new Task();
		$eet = $task->eet_value();
	}
	
	$inputs = array();
	
	$inputs['status'] = array(
		
		'#type' => 'select', 
		'#title' => 'Status', 
		'#id' => unique_id('edit-status'), 
		'#options' => array(
			'P' => array(
				'#title' => 'Pending', 
				'#value' => 'P'
			), 
			'I' => array(
				'#title' => 'In Progress', 
				'#value' => 'I'
			), 
			'C' => array(
				'#title' => 'Completed', 
				'#value' => 'C'
			)
		)
	);
	$inputs['status']['#options'][$task->status]['#selected'] = TRUE;
	
	$form_id = unique_id('task-edit-' . $tid);
	
	$inputs['description'] = array(
		'#type' => 'textfield', 
		'#id' => unique_id('edit-description'), 
		'#title' => 'Description', 
		'#value' => $task->description, 
		'#size' => 60
	);
	$inputs['details'] = array(
		'#type' => 'textarea', 
		'#id' => unique_id('edit-details'), 
		'#title' => 'Details', 
		'#rows' => 5, 
		'#cols' => 60, 
		'#value' => $task->details
	);
	
	_task_select_array($inputs, 'feature', 'description', 'fid', $task);
	_task_select_array($inputs, 'milestone', 'name', 'mid', $task);
	_task_select_array($inputs, 'developer', 'name', 'did', $task);
	
	$inputs['eet_wrapper'] = array(
		'#type' => 'html', 
		'#value' => '<div class="form-item-wrapper form-item">'
	);
	$inputs['eet_days'] = array(
		'#type' => 'textfield', 
		'#id' => unique_id('edit-eet-days'), 
		'#title' => 'Expected Elapsed Time', 
		'#description' => 'days', 
		'#value' => $eet['days'], 
		'#size' => 5
	);
	$inputs['eet_hours'] = array(
		'#type' => 'textfield', 
		'#id' => unique_id('edit-eet-hours'), 
		'#description' => 'hours', 
		'#value' => $eet['hours'], 
		'#size' => 5
	);
	$inputs['eet_wrapper_close'] = array(
		'#type' => 'html', 
		'#value' => '</div>'
	);
	$inputs['button_wrapper'] = array(
		'#type' => 'html', 
		'#value' => '<div class="form-item-wrapper">'
	);
	$inputs['cancel'] = array(
		'#type' => 'submit', 
		'#value' => 'Cancel', 
		'#id' => unique_id('cancel'), 
		'#attributes' => array(
			'class' => 'ui-button'
		)
	);
	
	if ($op == 'edit')
	{
		$inputs['cancel']['#attributes']['onclick'] = "$('#" . $form_id . "').get(0).setAttribute('action', '" . base_path() . "task?op=edit&tid=" . $task->tid . "');";
		$inputs['delete'] = array(
			
			'#type' => 'submit', 
			'#value' => 'Delete', 
			'#id' => unique_id('delete'), 
			'#attributes' => array(
				'class' => 'ui-button', 
				'onclick' => "$('#" . $form_id . "').get(0).setAttribute('action', '" . base_path() . "task?op=delete&subop=confirm&tid=" . $task->tid . "');"
			)
		);
		$inputs['save'] = array(
			'#type' => 'submit', 
			'#value' => 'Save', 
			'#id' => unique_id('save'), 
			'#attributes' => array(
				'class' => 'ui-button', 
				'onclick' => "$('#" . $form_id . "').get(0).setAttribute('action', '" . base_path() . "task?op=edit&subop=save&tid=" . $task->tid . "');"
			)
		);
	}
	else if ($op == 'clone')
	{
		$inputs['cancel']['#attributes']['onclick'] = "$('#" . $form_id . "').get(0).setAttribute('action', '" . base_path() . "task?op=edit&tid=" . $task->tid . "');";
		$inputs['save'] = array(
			'#type' => 'submit', 
			'#value' => 'Save', 
			'#id' => unique_id('save'), 
			'#attributes' => array(
				'class' => 'ui-button', 
				'onclick' => "$('#" . $form_id . "').get(0).setAttribute('action', '" . base_path() . "task?op=clone&subop=save&tid=" . $task->tid . "');"
			)
		);
	}
	else if ($op == 'add')
	{
		$inputs['cancel']['#attributes']['onclick'] = "$('#" . $form_id . "').get(0).setAttribute('action', '" . base_path() . "task');";
		$inputs['save'] = array(
			'#type' => 'submit', 
			'#value' => 'Save', 
			'#id' => unique_id('save'), 
			'#attributes' => array(
				'class' => 'ui-button', 
				'onclick' => "$('#" . $form_id . "').get(0).setAttribute('action', '" . base_path() . "task?op=add&subop=save&tid=" . $task->tid . "');"
			)
		);
	}
	
	$inputs['button_wrapper_close'] = array(
		'#type' => 'html', 
		'#value' => '</div>'
	);
	
	$task_form = array(
		
		'#id' => $form_id, 
		'#action' => base_path() . 'task?op=edit&subop=save&tid=' . $task->tid, 
		'#method' => 'POST', 
		'#validator' => 'task_edit_validate', 
		'#callback' => 'task_edit_submit', 
		'#inputs' => $inputs, 
		'#description' => 'All fields are required.', 
		'#attributes' => array(
			'class' => 'edit-task'
		)
	);
}

/**
 * task_edit_validate()
 * 
 * @param mixed $form_result
 * @return void
 */
function task_edit_validate(&$form_result)
{
	global $op;
	
	$values = $form_result['values'];
	if ($values['submit'] == 'Save')
	{
		$reload = FALSE;
		if (!isset($values['description']))
		{
			$reload = TRUE;
			form_error('description', 'You must specify a description.');
		}
		else if (strlen($values['description']) >= 255)
		{
			$reload = TRUE;
			form_error('description', 'The description must be less than 255 characters.');
		}
		
		if (!isset($values['details']))
		{
			$reload = TRUE;
			form_error('details', 'You must specify details.');
		}
		
		if ($op == 'add')
		{
			if ($values['feature'] <= 0)
			{
				form_error('developer', 'You must choose a feature.');
			}
			
			if ($values['milestone'] <= 0)
			{
				form_error('developer', 'You must choose a milestone.');
			}
			
			if ($values['developer'] <= 0)
			{
				form_error('developer', 'You must choose a developer.');
			}
		}
		
		if (isset($values['eet_days']) && !preg_match("/^[0-9\.]+$/", $values['eet_days']))
		{
			$reload = TRUE;
			form_error('eet_days', 'You must enter a positive, numerical value for both of the <em>Expected Elapsed Time</em> fields.');
		}
		
		if (isset($values['eet_hours']) && !preg_match("/^[0-9\.]+$/", $values['eet_hours']))
		{
			$reload = TRUE;
			form_error('eet_hours', 'You must enter a positive, numerical value for both of the <em>Expected Elapsed Time</em> fields.');
		}
		
		if ($reload)
		{
			task_edit_form($_GET['tid'], $form_result['values']);
		}
	}
}

/**
 * task_edit_submit()
 * 
 * @param mixed $form_result
 * @return void
 */
function task_edit_submit(&$form_result)
{
	$values = $form_result['values'];
	if ($values['submit'] == 'Save')
	{
		global $op;
		
		$task = '';
		if ($op == 'edit')
		{
			$task = new Task($_GET['tid']);
		}
		else if ($op = 'clone' || $op == 'add')
		{
			$task = new Task();
		}
		
		$task->status = $values['status'];
		$task->did = $values['developer'];
		$task->fid = $values['feature'];
		$task->mid = $values['milestone'];
		$task->description = $values['description'];
		$task->details = $values['details'];
		$task->eet = $task->eet_convert(array(
			'days' => $values['eet_days'], 
			'hours' => $values['eet_hours']
		));
		
		$task->save();
		
		system_redirect(base_path() . 'task?op=edit&tid=' . $task->tid);
	}
	else if ($values['submit'] != 'Delete')
	{
		system_redirect(base_path() . 'task');
	}
}

/**
 * task_delete_confirmation_form()
 * 
 * @param mixed $tid
 * @return void
 */
function task_delete_confirmation_form($tid)
{
	global $task_form;
	
	$form_id = unique_id('task-delete');
	$task_form = array(
		
		'#id' => $form_id, 
		'#action' => base_path() . 'task?op=delete&tid=' . $tid, 
		'#method' => 'POST', 
		'#validator' => 'task_delete_task_confirmation_validate', 
		'#callback' => 'task_delete_task_confirmation_submit', 
		'#inputs' => array(
			'confirm' => array(
				'#title' => 'Are you sure you want to delete this task?', 
				'#type' => 'checkbox', 
				'#description' => 'This task will be completely erased from the system.', 
				'#value' => 1, 
				'#checked' => FALSE
			), 
			'submit' => array(
				'#type' => 'submit', 
				'#value' => 'Delete', 
				'#attributes' => array(
					'onclick' => "$('#" . $form_id . "').get(0).setAttribute('action', '" . base_path() . "task?op=delete&tid=" . $tid . "');"
				)
			), 
			'cancel' => array(
				'#type' => 'submit', 
				'#value' => 'Cancel', 
				'#attributes' => array(
					'onclick' => "$('#" . $form_id . "').get(0).setAttribute('action', '" . base_path() . "task?op=delete&subop=cancel&tid=" . $tid . "');"
				)
			)
		)
	);
	
	if ($error = form_error('confirm'))
	{
		$task_form['#inputs']['confirm']['#attributes'] = array(
			'class' => 'error'
		);
		system_set_message($error, 'error');
	}
}

/**
 * task_delete_task_confirmation_validate()
 * 
 * @param mixed $form_result
 * @return void
 */
function task_delete_task_confirmation_validate(&$form_result)
{
	switch ($form_result['values']['submit'])
	{
		case 'Delete':
			$confirmation_form = FALSE;
			if (!isset($form_result['values']['confirm']) || $form_result['values']['confirm'] != 1)
			{
				form_error('confirm', 'Please confirm that you would like to delete this task, or click Cancel.');
				$confirmation_form = TRUE;
			}
			
			if ($confirmation_form)
			{
				front_delete_developer_confirmation_form($form_result['values']);
			}
			
			break;
		case 'Cancel':
			
			break;
	}
}

/**
 * task_delete_task_confirmation_submit()
 * 
 * @param mixed $form_result
 * @return void
 */
function task_delete_task_confirmation_submit(&$form_result)
{
	if ($form_result['values']['submit'] == 'Delete')
	{
		if (isset($_GET['tid']))
		{
			$description = db_result(db_query('SELECT description FROM task WHERE tid=%d', $_GET['tid']));
			
			$description = db_query('DELETE FROM task WHERE tid=%d', $_GET['tid']);
			if ($description)
			{
				system_set_message('The following task was successfully deleted: <code>' . $description . '</code>');
				system_redirect(base_path() . 'task');
			}
		}
	}
	else
	{
		system_redirect(base_path() . 'task?op=edit&tid=' . $_GET['tid']);
	}
}












